package belf.migrate.engine.job.structure.helper;

import belf.migrate.api.taskconf.JobContext;
import belf.migrate.api.util.EngineConf;
import belf.migrate.api.job.Job;
import belf.migrate.engine.job.JobResult;
import belf.migrate.engine.job.JobResultItem;
import lombok.extern.slf4j.Slf4j;

import java.util.List;
import java.util.concurrent.CountDownLatch;

/**
 * 使用大模型对源端SQL对象进行转换的基类。该基类的作用在于，使用CountDownLatch实现并发访问LLM。
 * 已知缺陷：同一对象（比如视图）之间可能存在依赖关系，需要考虑手动修复。
 */
@Slf4j
public abstract class SqlTransformTool extends NonTableTool {
    public SqlTransformTool(Job job) {
        super(job);
    }

    public SqlTransformTool(Job job, JobContext jobContext) {
        super(job, jobContext);
    }

    /**
     * 并行调用大模型进行SQL转换。
     * @param objectNames
     * @param jobResult
     */
    public void transform(List<Object> objectNames, JobResult jobResult) {
        int threads = Math.min(EngineConf.getInstance().getInt("llm.agent.number", 10),
                objectNames.size());
        int rounds = TaskTools.calculateRounds(objectNames.size(), threads);
        for (int round = 0; round < rounds; round++) {
            long timestamp1 = System.currentTimeMillis();
            CountDownLatch latch = new CountDownLatch(threads);
            for (int j = round * threads; j < Math.min(round * threads + threads, objectNames.size()); j++) {
                Thread thread = new Thread(new MyTask(jobResult,
                        objectNames.get(j),
                        latch));
                thread.start();
            }

            try {
                latch.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            long timestamp2 = System.currentTimeMillis();
            String seconds = String.format("%.2f seconds", (timestamp2-timestamp1)/1000.0);
            log.debug("{} Seconds，Batch Transformed SQL on Round {}, Total Rounds: {}", seconds, round+1, rounds);
        }
    }

    private class MyTask implements Runnable {
        private JobResult jobResult;
        private Object object;
        private CountDownLatch latch;

        public MyTask(JobResult jobResult, Object object, CountDownLatch latch) {
            this.jobResult = jobResult;
            this.object = object;
            this.latch = latch;
        }

        @Override
        public void run() {
            try {
                JobResultItem jobResultItem = process(object);
                jobResult.addItem(jobResultItem);

            } catch (Exception e) {

            } finally {
                latch.countDown();
            }
        }
    }

    /**
     * 调用LLM大模型进行具体的SQL转换，转换成功，在目标端执行SQL
     * @param object
     * @return
     */
    protected abstract JobResultItem process(Object object);
}
